<?php
/**
 * Created by PhpStorm.
 * User: bililovy
 * Date: 19-6-21
 * Time: 下午8:07
 * Description: 渐变图片填充
 */

namespace ServiceSdk\Utils\Image;

use xiaoyaoSDK\Services\BaseService;
use ServiceSdk\Utils\Image\image\Exception as ImageException;

class GradientFill extends BaseService
{
    private $width;
    private $height;
    private $direction;
    private $startcolor;
    private $endcolor;
    private $step;

    /**
     * 构造方法
     *
     * @param int $width            图片宽度
     * @param int $height           图片高度
     * @param int $direction        填充方向
     * @param string $startHexColor 填充开始颜色值（16进制）
     * @param string $endHexColor   填充结束颜色值 （16进制）
     * @param int $step             填充补偿（值越小，渐变越光滑）
     */
    public function __construct(int $width, int $height, int $direction, string $startHexColor, string $endHexColor, int $step = 0)
    {
        $this->width = $width;
        $this->height = $height;
        $this->direction = $direction;
        $this->startcolor = $startHexColor;
        $this->endcolor = $endHexColor;
        $this->step = intval(abs($step));

        if (function_exists('imagecreatetruecolor')) {
            $this->image = imagecreatetruecolor($this->width, $this->height);
        } elseif (function_exists('imagecreate')) {
            $this->image = imagecreate($this->width, $this->height);
        } else {
            throw new ImageException('无法创建图片');
        }
        // 执行填充
        $this->fill($this->image, $this->direction, $this->startcolor, $this->endcolor);
    }

    /**
     * Description: 获取填充好的图片
     * @Author: Bililovy
     * @Date  : 19-6-21 下午8:14
     */
    public function getImage()
    {
        $this->image;
    }

    /**
     * Description: 直接显示图片
     * @return bool
     * @Author: Bililovy
     * @Date  : 19-6-21 下午8:17
     */
    function display()
    {
        $im = $this->image;
        if (function_exists("imagepng")) {
            header("Content-type: image/png");
            imagepng($im);
        } elseif (function_exists("imagegif")) {
            header("Content-type: image/gif");
            imagegif($im);
        } elseif (function_exists("imagejpeg")) {
            header("Content-type: image/jpeg");
            imagejpeg($im, "", 0.5);
        } elseif (function_exists("imagewbmp")) {
            header("Content-type: image/vnd.wap.wbmp");
            imagewbmp($im);
        } else {
            throw new ImageException('缺少可用的图片处理方法，请检查GD库扩展');
        }
        unset($im);

        return true;
    }


    // The main function that draws the gradient
    public function fill($im, $direction, $start, $end)
    {

        switch ($direction) {
            case 1:
                $line_numbers = imagesx($im);
                $line_width = imagesy($im);
                list($r1, $g1, $b1) = $this->hex2rgb($start);
                list($r2, $g2, $b2) = $this->hex2rgb($end);
            break;
            case 2:
                $line_numbers = imagesy($im);
                $line_width = imagesx($im);
                list($r1, $g1, $b1) = $this->hex2rgb($start);
                list($r2, $g2, $b2) = $this->hex2rgb($end);
            break;
            case 3:
                $width = imagesx($im);
                $height = imagesy($im);
                $rh = $height > $width ? 1 : $width / $height;
                $rw = $width > $height ? 1 : $height / $width;
                $line_numbers = min($width, $height);
                $center_x = $width / 2;
                $center_y = $height / 2;
                list($r1, $g1, $b1) = $this->hex2rgb($end);
                list($r2, $g2, $b2) = $this->hex2rgb($start);
                imagefill($im, 0, 0, imagecolorallocate($im, $r1, $g1, $b1));
            break;
            case 4:
                $width = imagesx($im);
                $height = imagesy($im);
                $rh = $height > $width ? 1 : $width / $height;
                $rw = $width > $height ? 1 : $height / $width;
                $line_numbers = sqrt(pow($width, 2) + pow($height, 2));
                $center_x = $width / 2;
                $center_y = $height / 2;
                list($r1, $g1, $b1) = $this->hex2rgb($end);
                list($r2, $g2, $b2) = $this->hex2rgb($start);
            break;
            case 5:
                $width = imagesx($im);
                $height = imagesy($im);
                $line_numbers = sqrt(pow($width, 2) + pow($height, 2));
                $center_x = $width / 2;
                $center_y = $height / 2;
                $rh = $rw = 1;
                list($r1, $g1, $b1) = $this->hex2rgb($end);
                list($r2, $g2, $b2) = $this->hex2rgb($start);
            break;
            case 6:
                $width = imagesx($im);
                $height = imagesy($im);
                $line_numbers = min($width, $height);
                $center_x = $width / 2;
                $center_y = $height / 2;
                $rh = $rw = 1;
                list($r1, $g1, $b1) = $this->hex2rgb($end);
                list($r2, $g2, $b2) = $this->hex2rgb($start);
                imagefill($im, 0, 0, imagecolorallocate($im, $r1, $g1, $b1));
            break;
            case 7:
            case 8:
                $width = imagesx($im);
                $height = imagesy($im);
                $line_numbers = max($width, $height) / 2;
                list($r1, $g1, $b1) = $this->hex2rgb($end);
                list($r2, $g2, $b2) = $this->hex2rgb($start);
            break;
            case 9:
                list($r1, $g1, $b1) = $this->hex2rgb($end);
                list($r2, $g2, $b2) = $this->hex2rgb($start);
                $width = imagesx($im);
                $height = imagesy($im);
                $rh = $height > $width ? 1 : $width / $height;
                $rw = $width > $height ? 1 : $height / $width;
                $line_numbers = min($width, $height);
            break;
            default:
                throw new ImageException('不支持的填充方向类型');
        }

        for ($i = 0; $i < $line_numbers; $i = $i + 1 + $this->step) {
            // old values :
            $old_r = $r ?? '';
            $old_g = $g ?? '';
            $old_b = $b ?? '';
            // new values :
            $r = ($r2 - $r1 != 0) ? intval($r1 + ($r2 - $r1) * ($i / $line_numbers)) : $r1;
            $g = ($g2 - $g1 != 0) ? intval($g1 + ($g2 - $g1) * ($i / $line_numbers)) : $g1;
            $b = ($b2 - $b1 != 0) ? intval($b1 + ($b2 - $b1) * ($i / $line_numbers)) : $b1;
            // if new values are really new ones, allocate a new color, otherwise reuse previous color.
            // There's a "feature" in imagecolorallocate that makes this function
            // always returns '-1' after 255 colors have been allocated in an image that was created with
            // imagecreate (everything works fine with imagecreatetruecolor)
            if ("$old_r,$old_g,$old_b" != "$r,$g,$b") {
                $fill = imagecolorallocate($im, $r, $g, $b);
            }
            switch ($direction) {
                case 1:
                    imagefilledrectangle($im, 0, $i, $line_width, $i + $this->step, $fill);
                break;
                case 2:
                    imagefilledrectangle($im, $i, 0, $i + $this->step, $line_width, $fill);
                break;
                case 3:
                case 4:
                case 5:
                case 6:
                    imagefilledellipse($im, $center_x, $center_y, ($line_numbers - $i) * $rh, ($line_numbers - $i) * $rw, $fill);
                break;
                case 7:
                case 8:
                    imagefilledrectangle($im, $i * $width / $height, $i * $height / $width, $width - ($i * $width / $height), $height - ($i * $height / $width), $fill);
                break;
                case 9:
                    imagefilledpolygon($im, array (
                        $width / 2,
                        $i * $rw - 0.5 * $height,
                        $i * $rh - 0.5 * $width,
                        $height / 2,
                        $width / 2,
                        1.5 * $height - $i * $rw,
                        1.5 * $width - $i * $rh,
                        $height / 2
                    ), 4, $fill);
                break;
                default:
            }
        }
    }

    // #ff00ff -> array(255,0,255) or #f0f -> array(255,0,255)
    function hex2rgb($color)
    {
        $color = str_replace('#', '', $color);
        $s = strlen($color) / 3;
        $rgb[] = hexdec(str_repeat(substr($color, 0, $s), 2 / $s));
        $rgb[] = hexdec(str_repeat(substr($color, $s, $s), 2 / $s));
        $rgb[] = hexdec(str_repeat(substr($color, 2 * $s, $s), 2 / $s));

        return $rgb;
    }


}